using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using RPGOnline.Controls.Map.Layers;
using RPGOnline.Controls.Map.Layers.FogOfWar;
using RPGOnline.Controls.Map.Layers.Obstruction;
using RPGOnline.Extensions;
using RPGOnline.Properties;
using RPGOnline.Rendering;
using Light = RPGOnline.Controls.Map.Layers.Lighting.Light;
using LightsCollection = RPGOnline.Controls.Map.Layers.Lighting.LightsCollection;

namespace RPGOnline.Controls.Map
{
    public class Map
    {
		private readonly Renderer m_renderer;

        [Category("Map")]
        public Size TileSize { get; private set; }
        [Category("Map")]
        public Size MapSize { get; private set; }
        [Browsable(false)]
        public List<ICellsLayer> Layers { get { return m_layers; } }
        [Browsable(false)]
        public List<MapTileset> TileSets { get { return m_tileSets; } }
        [Browsable(false)]
        public ICellsLayer CurrentLayer { get; set; }
        public LightsCollection Lights
        {
            get { return LightingLayer.Lights; }
            set { LightingLayer.Lights = value; }
        }

		private List<ICellsLayer> m_layers = new List<ICellsLayer>();
        private List<MapTileset> m_tileSets = new List<MapTileset>();

	    [Browsable(false)]
        public LightingLayer LightingLayer { get; private set; }
        [Browsable(false)]
        public OverlayLayer OverlayLayer { get; private set; }
        [Browsable(false)]
        public ObstructionLayer ObstructionLayer { get; private set; }
        [Browsable(false)]
        public FogOfWarLayer FogOfWarLayer { get; private set; }

    	public Map(Renderer renderer, Size tileSize, Size mapSize)
        {
    	    m_renderer = renderer;
    	    TileSize = tileSize;
            MapSize = mapSize;

            NewLayer("Terrain");
            CurrentLayer = m_layers[0];
            LightsCollection lightsCollection = new LightsCollection(this);

            LightingLayer = new LightingLayer(m_renderer, this, lightsCollection);
            OverlayLayer = new OverlayLayer(m_renderer, this);
            ObstructionLayer = new ObstructionLayer(this, lightsCollection);
            //FogOfWarLayer = new FogOfWarLayer(m_renderer, this);
        }

        public MapLayer NewLayer(string name)
        {
            MapLayer mapLayer = new MapLayer(m_renderer, name, this);
            m_layers.Add(mapLayer);
            return mapLayer;
        }

        public void DrawLayers()
        {
            m_layers.ForEach(l => l.Draw());
        }

        public void DrawObstruction()
        {
            //ObstructionLayer.Draw(m_renderer);
        }

	    public void UpdateLighting()
	    {
		    LightingLayer.Update();
	    }

        public void DrawLighting()
        {
            LightingLayer.Draw();
        }

        public void DrawOverlay()
        {
            OverlayLayer.Draw();
        }

        public void GetCellCoordsAt(Point position, out Point cellCoords)
        {
            cellCoords = new Point(
                position.X / TileSize.Width,
                position.Y / TileSize.Height
            );
        }

        public void AddLight(Color color, Vector2 point, float radius)
        {
            LightingLayer.Lights.Add(new Light(this)
            {
                Color = color, Position = point, Radius = radius
            });
        }

	    public void DrawObstructionMap()
	    {
		    m_layers.Skip(1)
				.ForEach(l => l.Draw());
	    }


	    public void DrawLights()
	    {
		    LightingLayer.DrawPlaceholders();
	    }

	    public void DrawAmbient()
	    {
		    Matrix screenMatrix = Matrix.Scaling(MapSize.Width*TileSize.Width, MapSize.Height*TileSize.Height, 1);

		    using (m_renderer.BeginAmbientPass(Color.FromArgb(255, 50, 50, 50)))
		    {
			    m_renderer.DrawQuad(screenMatrix, Matrix.Identity, m_renderer.GetFirstPassTexture());
		    }
	    }
    }
}